import { ipcMain } from 'electron';
import fs from 'fs/promises';
import path from 'path';

/**
 * @description 读取配置文件
 * @param {string} filePath - 配置文件的绝对路径
 * @returns {Promise<object>} - 解析后的配置对象，如果文件不存在则返回空对象
 * @throws {Error} - 如果读取或解析文件失败
 */
async function readConfigFile(filePath) {
  try {
    const data = await fs.readFile(filePath, 'utf8');
    return JSON.parse(data);
  } catch (error) {
    if (error.code === 'ENOENT') {
      // 文件不存在，返回空对象，表示这是一个新的配置
      return {};
    }
    console.error(`读取或解析配置文件失败 ${filePath}:`, error);
    throw new Error(`读取或解析配置文件失败: ${error.message}`);
  }
}

/**
 * @description 写入配置文件
 * @param {string} filePath - 配置文件的绝对路径
 * @param {object} config - 要写入的配置对象
 * @returns {Promise<void>}
 * @throws {Error} - 如果写入文件失败
 */
async function writeConfigFile(filePath, config) {
  try {
    // 确保目录存在，如果不存在则递归创建
    await fs.mkdir(path.dirname(filePath), { recursive: true });
    await fs.writeFile(filePath, JSON.stringify(config, null, 2), 'utf8');
  } catch (error) {
    console.error(`写入配置文件失败 ${filePath}:`, error);
    throw new Error(`写入配置文件失败: ${error.message}`);
  }
}

/**
 * @description 注册配置相关的 IPC 处理函数
 */
function handleConfig() {
  /**
   * 处理渲染进程发起的读取配置请求
   * @param {Electron.IpcMainInvokeEvent} event - IPC 事件对象
   * @param {string} filePath - 配置文件的绝对路径
   * @returns {Promise<{success: boolean, data?: object, error?: string}>}
   */
  ipcMain.handle('config:read', async (event, filePath) => {
    console.log(`尝试从以下路径读取配置: ${filePath}`);
    try {
      const config = await readConfigFile(filePath);
      return { success: true, data: config };
    } catch (error) {
      return { success: false, error: error.message };
    }
  });

  /**
   * 处理渲染进程发起的写入配置请求
   * @param {Electron.IpcMainInvokeEvent} event - IPC 事件对象
   * @param {string} filePath - 配置文件的绝对路径
   * @param {object} newConfig - 要写入或合并的新配置对象
   * @returns {Promise<{success: boolean, error?: string}>}
   */
  ipcMain.handle('config:write', async (event, filePath, newConfig) => {
    console.log(`尝试向以下路径写入配置: ${filePath}，数据为:`, newConfig);
    try {
      // 读取现有配置，如果文件不存在则返回空对象
      let existingConfig = await readConfigFile(filePath);
      // 合并新配置与现有配置（新配置会覆盖同名属性，并添加新属性）
      const updatedConfig = { ...existingConfig, ...newConfig };
      await writeConfigFile(filePath, updatedConfig);
      return { success: true };
    } catch (error) {
      return { success: false, error: error.message };
    }
  });
}

export default handleConfig;